iT邦幫忙

2026 iThome 鐵人賽

DAY 27
0
Build on Google AI

30 天玩轉 Google AI 全家桶:初學者的隨身 Coding 助理養成記系列 第 27 篇

Day 27:代理人接手!讓 Antigravity 自動跑完「修補 → 驗收」流程

  • 分享至 

  • xImage
  •  

昨天,DevPulse 有了本機 CLI,只要輸入 devpulse run <filePath>,就能審查指定的檔案。

不過完整的「修復 → 驗收」流程,目前還是得手動一步步串起來:先在 Genkit Developer UI 對三個檔案各跑一次 patchFlow,再切換 DEVPULSE_SOURCE_DIR 跑測試,最後自己比對 diff。三個檔案、每個檔案好幾個步驟,全是重複操作。

今天不新增 AI 邏輯,而是把這些重複操作交給 Antigravity 的代理人。

今天要完成三件事:

  1. 補上 devpulse fix 指令,讓 patchFlow 也能從終端機呼叫。
  2. 用 AGENTS.md 替代理人訂好流程與界線。
  3. 交付任務,讓 Antigravity 自己跑完「修補 → 測試 → 回報」。

一、為什麼這件事適合交給代理人

前面幾天,每一步都是「我下指令,我看結果」。代理人的差別在於:它會自己整理步驟、在終端機執行指令、讀取輸出,再決定下一步。

今天的流程剛好符合三個條件:步驟固定、每一步都有明確的結果(指令是否成功、測試是否通過)、最後可以由測試客觀驗收。

npm test(測試 samples/)→ 預期三個紅燈
          ↓
devpulse fix × 3 → 產生 fixed/ 修復檔
          ↓
npm run test:fixed → 看綠燈或紅燈
          ↓
代理人回報結果表

這裡的分工要先講清楚:

  • DevPulse(Gemini + Genkit):負責產生補丁。
  • Jest 測試:負責判定補丁有沒有修好。
  • Antigravity 代理人:負責執行流程、回報結果,不負責改程式。

如果讓代理人自己動手改程式,就分不出綠燈是 DevPulse 的功勞,還是代理人偷偷修好的。所以今天它只當「操作員」。

二、先給代理人一個能呼叫的指令:devpulse fix

目前 patchFlow 只能從 Developer UI 觸發,代理人在終端機裡沒有指令可以呼叫它。所以要先在 bin/devpulse.mjs 補上 fix,總共四處小改動。

1. 匯入 patchFlow(放在原本的 codeReviewFlow 匯入下面):

import { patchFlow } from "../src/patchFlow.mjs";

2. 說明頁加上兩行:

  devpulse fix <filePath>  產生修復檔到 fixed/(不會改動原始檔)
  devpulse fix samples/sql.cjs

3. 新增 runFix() 函式(放在 showHelp() 後面):

async function runFix(filePath) {
  console.log(chalk.cyan.bold("\nDevPulse 產生修復檔"));
  console.log(chalk.gray(`分析檔案:${filePath}`));

  try {
    const result = await patchFlow({ filePath });

    console.log(chalk.green(`\n✓ 修復檔已寫入:${result.outputPath}`));
    console.log(chalk.gray(`補丁數量:${result.patches.length}`));

    for (const patch of result.patches) {
      console.log(`  第 ${patch.startLine}-${patch.endLine} 行:${patch.reason}`);
    }

    console.log(
      chalk.yellow("\n補丁已套用,但還沒有驗證。請執行:npm run test:fixed"),
    );
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    console.error(chalk.red.bold("\n產生修復檔失敗:"), message);
    process.exitCode = 1;
  }
}

4. 在 main() 裡讓 fix 通過指令檢查,並在算出 filePath 之後分流:

  if (command !== "run" && command !== "fix") {
    // ...原本的錯誤處理不變
  }
  const filePath = path.resolve(process.cwd(), targetPath);

  if (command === "fix") {
    await runFix(filePath);
    return;
  }

幾個設計重點:

  • fix 只會把結果寫進 fixed/,不會動 samples/,延續昨天「CLI 不擅自改動原始檔」的原則。
  • 失敗時設定 process.exitCode = 1。對代理人來說,結束碼就是「這一步有沒有成功」最直接的訊號。
  • patchFlow 寫入的是相對路徑 fixed/,所以要在 devpulse/ 專案根目錄執行。

接著在 package.json 的 scripts 加上一行,保留原本的 test 不動:

npm install -D cross-env
"test:fixed": "cross-env DEVPULSE_SOURCE_DIR=fixed npm test"

Day 25 時,Windows PowerShell 與 macOS/Linux 設定環境變數的語法不一樣。cross-env 負責抹平這個差異,之後不管哪個系統,驗收 fixed/ 都只要一行 npm run test:fixed。對代理人來說,少一個需要臨場判斷的地方,就少一個出錯的機會。

交給代理人之前,先自己跑一次:

node ./bin/devpulse.mjs fix samples/sql.cjs
npm run test:fixed

指令本身有問題的話,代理人只會把錯誤放大。確認 fixed/sql.cjs 有出現,再往下走。

三、AGENTS.md:把規則寫給代理人

Antigravity 會讀取專案根目錄的 AGENTS.md,把它當成長期規則(也支援 GEMINI.md 與 .agents/rules/;兩份同時存在時以 GEMINI.md 優先,所以今天只放一份就好)。

【發文前請確認】規則檔的讀取方式與檔名,請以你使用的 Antigravity 版本為準。

在 devpulse/ 根目錄建立 AGENTS.md:

# DevPulse 代理人守則

## 專案說明
DevPulse 是本機的程式碼診斷小幫手。
- `samples/`:三個刻意寫錯的範例(原始檔)
- `tests/`:驗收條件
- `fixed/`:DevPulse 產生的修復檔

## 可用指令(一律在專案根目錄執行)
- `npm test`:測試 `samples/` 原始檔。三個範例預期是紅燈,這是刻意的,不要去修。
- `node ./bin/devpulse.mjs fix <檔案>`:呼叫 Gemini 產生修復檔,寫入 `fixed/`。
- `npm run test:fixed`:用同一組測試驗收 `fixed/`。

## 工作流程
1. 先執行 `npm test`,記錄原始檔的測試結果。
2. 對 `samples/` 裡的每個 `.cjs` 檔,各執行一次 `fix`。
3. 執行 `npm run test:fixed`。
4. 如果有檔案失敗:記下 Jest 的 Expected 與 Received,再用
   `git diff --no-index samples/<檔名> fixed/<檔名>` 找出補丁問題。
   對失敗的檔案最多重跑一次 `fix`,然後再測一次。

## 不可以做的事
- 不修改 `tests/` 與 `samples/` 裡的任何檔案。
- 不手動編輯 `fixed/` 裡的檔案,它必須是 DevPulse 的產出。
- 不讀取、不印出 `.env`,也不把金鑰寫進任何檔案或回報。
- 不執行 `git commit`、`git push`,不安裝或升級套件。

## 回報格式
用一張表回報:檔案|原始測試|修復後測試|備註。
附上實際的測試結果,不要只寫「已完成」。

這份守則有幾個刻意的寫法:

  • 講明紅燈是刻意的。 不寫的話,代理人看到 npm test 失敗,很可能會想「幫你修好」。
  • 失敗時只回報,不手動修。 一旦代理人手改 fixed/,綠燈就不再代表 DevPulse 的補丁有效,Day 25 的驗收也就失去意義。
  • 用 node ./bin/devpulse.mjs,而不是 devpulse。 這樣不依賴 npm link 的全域指令,避免代理人的終端機找不到它。
  • 不碰 .env。 .gitignore 只是叫 git 不要追蹤這個檔案,並不保證代理人讀不到它。

要特別注意:AGENTS.md 是「請代理人遵守」的規則,不是技術上的限制。真正的限制要靠下一段的權限設定。

四、交付任務:提示詞與權限

用 Antigravity 開啟 devpulse/ 資料夾,在 Agent 面板貼上今天的提示詞:

請依照 AGENTS.md 的流程,替 DevPulse 做一次完整驗收:

1. 先執行 npm test,確認 samples/ 的三個範例目前是紅燈。
2. 對 samples/ 裡的每個 .cjs 檔各執行一次 fix。
3. 執行 npm run test:fixed。
4. 用表格回報每個檔案在修復前後的測試結果。

如果修復後仍有測試失敗,請只回報原因,最多重跑一次 fix。
不要修改測試,也不要手動編輯 fixed/ 裡的檔案。

長期規則放在 AGENTS.md,這次任務放在提示詞,所以提示詞可以很短。

接著是權限。第一次執行終端機指令時,請讓 Antigravity 先詢問你,不要一開始就全部自動放行,並且只允許這幾種指令:

  • node ./bin/devpulse.mjs fix ...
  • npm test、npm run test:fixed
  • git diff

其他指令一律拒絕。如果你的版本有 Strict Mode,可以先打開,由它搭配權限設定限制代理人能讀寫哪些檔案。

另外,任務範圍刻意收得很小:三個檔案、失敗最多重試一次。免費方案的代理人額度有限,不要讓它在失敗時無限重試。

五、執行成果與反饋

送出提示詞後,可以觀察代理人是否照 AGENTS.md 的順序走:先跑 npm test 確認紅燈、對三個檔案各執行 fix、再跑 npm run test:fixed,最後回報。

【發文前請替換】貼上 Antigravity 面板截圖:任務步驟、授權詢問、最終回報表。

如果三個補丁都符合測試契約,最後的回報大致會像這樣(以下是輸出示意,實際內容以你的執行結果為準):

檔案 原始測試 修復後測試 備註
async-await.cjs FAIL PASS 改用 for...of 搭配 await
sql.cjs FAIL PASS 改用 ? 佔位符並傳入參數陣列
boundary.cjs FAIL PASS 缺少 profile 時回傳 Unknown

如果其中有一個檔案仍然是 FAIL,那反而是今天最值得記錄的結果。請看代理人是否依守則「只回報原因」、最多重試一次,而不是偷偷改測試或手動編輯 fixed/。

不要只相信代理人的回報。 跑完後,自己再驗收一次:

npm run test:fixed
git status --short samples tests

第一行確認測試結果和代理人回報的一致;第二行確認 samples/ 與 tests/ 沒有被動過,應該沒有任何輸出。


Day 27 完成

  • ✅ 新增 devpulse fix,讓 patchFlow 可以從終端機呼叫
  • ✅ 新增 test:fixed 指令,用 cross-env 統一各系統的驗收方式
  • ✅ 撰寫 AGENTS.md,替代理人訂好流程與界線
  • ✅ 交付任務,讓 Antigravity 自動跑完「修補 → 驗收 → 回報」
  • ✅ 自己再驗證一次,確認代理人的回報可靠

下一篇 Day 28:代理人會讀程式碼,也會執行指令。如果程式碼的註解裡藏著一句「忽略以上規則」,會發生什麼事?明天來實測 Prompt Injection,看看 DevPulse 會不會被帶偏。

參考資料


上一篇
Day 26:打造本機 CLI:用單行指令呼叫你的 DevPulse
系列文
30 天玩轉 Google AI 全家桶:初學者的隨身 Coding 助理養成記 共 27 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言